<?php

namespace App\Models;

use App\Enums\MemberBalanceType;
use App\Enums\MemberMoneyLogType;
use App\Enums\PayChannel;
use App\Enums\TradeStatus;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Laravel\Sanctum\HasApiTokens;

/**
 * @method static withPhone($phone)
 */
class Member extends Authenticatable
{
    use HasFactory, SoftDeletes, HasApiTokens, Notifiable;

    protected $fillable = [
        'name', 'phone', 'nickname', 'openid', 'money', 'give_money',
        'all_consumption', 'all_recharge', 'all_sparring_consumption',
        'avatar', 'assistant_status', 'sex', 'member_level', 'member_month_level',
        'store_id', 'password', 'table_give_money', 'table_money',
    ];

    public function moneyLogs()
    {
        return $this->hasMany(MemberMoneyLog::class);
    }

    public function registerStore()
    {
        return $this->belongsTo(Store::class, 'store_id');
    }

    public function scopeWithPhone($query, $phone)
    {
        return $query->where('phone', $phone);
    }

    public function checkPassword($password)
    {
        if ($this->password != $password)
            return false;

        return true;
    }

    public static function getOrCreate($telephone)
    {
        $member = Member::withPhone($telephone)->first();

        if (!empty($member))
            return $member;

        return Member::create([
            'name' => '用户'.time(),
            'phone' => $telephone
        ]);
    }

    public static function login($telephone)
    {
        $member = Member::getOrCreate($telephone);

        $token = $member->createToken('member');

        $member->token = $token->plainTextToken;

        return $member;
    }

    public function recharge(MemberBalanceType $balanceType, $money, PayChannel $channel, User|null $operator, Store|null $store, string $msg, $giveMoney = 0)
    {
        if (in_array($channel, [
            PayChannel::Member, PayChannel::Bad
        ]))
            throw new \Exception('会员卡充值无法使用挂单和会员卡支付渠道');

        DB::transaction(function () use ($money, $channel, $operator, $store, $msg, $giveMoney, $balanceType, &$log) {

            if ($balanceType == MemberBalanceType::General) {

                $beforeMoney = $this->money;
                $this->money += ($money + $giveMoney);
                $this->give_money += $giveMoney;
                $afterMoney = $this->money;
            } else {

                $beforeMoney = $this->table_money;
                $this->table_money += ($money + $giveMoney);
                $this->table_give_money += $giveMoney;
                $msg = '桌台'.$msg;
                $afterMoney = $this->table_money;
            }
            $this->save();

            $log = $this->moneyLogs()->create([
                'user_id' => $operator->id ?? 0,
                'store_id' => $store->id ?? $operator->store_id ?? 0,
                'money' => $money,
                'content' => $msg,
                'channel' => $channel->value,
                'type' => MemberMoneyLogType::In,
                'give_money' => $giveMoney,
                'before_money' => $beforeMoney,
                'after_money' => $afterMoney,
                'balance_type' => $balanceType,
            ]);
        });

        return $log;
    }

//    public function consume($money, User $operator, string $msg, Order|null $order=null)
//    {
//        if ($this->money < $money)
//            throw new \Exception('会员卡余额不足');
//
//        DB::transaction(function () use ($money, $operator, $msg, $order, &$log) {
//
//            $beforeMoney = $this->money;
//            $this->money -= $money;
//            $this->save();
//
//            $log = $this->moneyLogs()->create([
//                'user_id' => $operator->id,
//                'store_id' => $operator->store_id,
//                'money' => $money * -1,
//                'content' => $msg,
//                'channel' => PayChannel::Member,
//                'type' => MemberMoneyLogType::Out,
//                'out_id' => $order->id,
//                'before_money' => $beforeMoney,
//                'after_money' => $this->money,
//                'balance_type' => MemberBalanceType::General,
//            ]);
//        });
//
//        return $log;
//    }

    public function orderCheck(Order $order, User $operator, string $msg)
    {
        //会员卡支付，但是要判断桌台余额和通用余额，桌台item的费用优先用桌台余额
        DB::transaction(function () use ($order, $operator, $msg) {

            $disMoney = 0;
            if ($this->table_money != 0) {

                $beforeMoney = $this->table_money;
                $tableItem = $order->getTableItem();
                if (($this->money + $this->table_money) < $tableItem->money)
                    throw new \Exception('会员卡余额不足');

                if ($this->table_money >= $tableItem->money) {

                    $this->table_money -= $tableItem->money;
                } else {

                    $this->table_money = 0;
                    $this->money -= ($tableItem->money - $this->table_money);
                }

                $disMoney = $tableItem->money;

                $this->moneyLogs()->create([
                    'user_id' => $operator->id,
                    'store_id' => $operator->store_id,
                    'money' => $disMoney * -1,
                    'content' => '桌台费'.$msg,
                    'channel' => PayChannel::Member,
                    'type' => MemberMoneyLogType::Out,
                    'out_id' => $order->id,
                    'before_money' => $beforeMoney,
                    'after_money' => $this->table_money,
                    'balance_type' => MemberBalanceType::Table,
                ]);
            }

            $beforeMoney = $this->money;
            if ($this->money < ($order->money - $disMoney))
                throw new \Exception('会员卡余额不足');

            $this->money -= ($order->money - $disMoney);
            $this->save();

            $this->moneyLogs()->create([
                'user_id' => $operator->id,
                'store_id' => $operator->store_id,
                'money' => ($order->money - $disMoney) * -1,
                'content' => $msg,
                'channel' => PayChannel::Member,
                'type' => MemberMoneyLogType::Out,
                'out_id' => $order->id,
                'before_money' => $beforeMoney,
                'after_money' => $this->money,
                'balance_type' => MemberBalanceType::General,
            ]);
        });
    }
}
